package com.luxsoft.siipap.em.replica.importadores.cxc;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.luxsoft.siipap.cxc.model.AplicacionDePago;
import com.luxsoft.siipap.cxc.model.Cargo;
import com.luxsoft.siipap.cxc.model.OrigenDeOperacion;
import com.luxsoft.siipap.cxc.model.Pago;
import com.luxsoft.siipap.cxc.model.PagoConCheque;
import com.luxsoft.siipap.cxc.model.PagoConDeposito;
import com.luxsoft.siipap.cxc.model.PagoConEfectivo;
import com.luxsoft.siipap.cxc.model.PagoConTarjeta;
import com.luxsoft.siipap.cxc.model.PagoDeDiferencias;
import com.luxsoft.siipap.em.replica.importadores.ImportacionCanceledException;
import com.luxsoft.siipap.em.replica.importadores.ImportadorSupport;
import com.luxsoft.siipap.model.Periodo;
import com.luxsoft.siipap.model.core.Cliente;
import com.luxsoft.siipap.service.ServiceLocator2;
import com.luxsoft.siipap.util.DBUtils;

/**
 * Importa los pagos y sus aplicaciones
 * 
 * @author Ruben Cancino Ramos
 *
 */
public class ImportadorDePagosDeContado implements RowCallbackHandler{
	
	
	
	private Logger logger=Logger.getLogger(getClass());
	
	/**
	 * Importa un pago desde SiipapWin (Oracle)
	 * 
	 * @param id
	 * @return
	 */
	public Pago importar(Long id){
		String sql="SELECT * FROM SW_PAGOS WHERE PAGO_ID=? AND PAGOM_ID IS NULL";
		//List<Pago> res=getOrigenTemplate().query(sql, new Object[]{id}, null);		
		return null;
	}
	
	/**
	 * Importa todas las notas de un periodo para el tipo indicado
	 * 
	 * @param periodo
	 * 
	 */
	public void importar(final Periodo periodo){		
		
		Object[] params=new Object[]{
			new SqlParameterValue(Types.DATE,periodo.getFechaInicial())	
			,new SqlParameterValue(Types.DATE,periodo.getFechaFinal())
		};		
		
		String sql="SELECT * FROM SW_PAGOS  A WHERE A.FECHA BETWEEN ? AND ? " +
				" AND ORIGEN IN(\'MOS\',\'CAM\')" +
				" AND FORMADEPAGO NOT IN(\'U\',\'T\',\'A\',\'S\',\'K\')" +
				" AND IMPORTE>0 ORDER BY PAGO_ID ";
		
		getOrigenTemplate().query(sql, params,this);
		
	}
	
	public void processRow(ResultSet rs) throws SQLException {
		
		
		//Number numero=(Number)rs.getObject("NUMERO"); //Numero de la factura
		
		//String DESCFORMADEPAGO=rs.getString("DESCFORMADEPAGO");
		
		String REFERENCIA=rs.getString("REFERENCIA");
		String DESCREFERENCIA=rs.getString("DESCREFERENCIA");
		
		String COMENTARIO=MessageFormat.format("{0}  {1}", REFERENCIA,DESCREFERENCIA);
		COMENTARIO=StringUtils.substring(COMENTARIO, 0, 250);
		Number IMPORTE=(Number)rs.getBigDecimal("IMPORTE");
		BigDecimal total=BigDecimal.valueOf(IMPORTE.doubleValue());
		
		String fp=rs.getString("FORMADEPAGO");
		Pago p=null;
		if( ("E".equals(fp)) || ("S".equals(fp)) || ("A".equals(fp))){
			p=new PagoConEfectivo();
			p.setComentario("PAGO TIPO: "+fp);
			
		}else if("N".equals(fp) || "O".equals(fp) ){				
			PagoConDeposito pd=new PagoConDeposito();
			pd.setEfectivo(total);			
			p=pd;
		}else if( ("B".equals(fp)) || ("C".equals(fp)) || ("Q".equals(fp)) ){
			p=new PagoConTarjeta();				
			
		}else if("H".equals(fp) || "Y".equals(fp) ){				
			p=new PagoConCheque();
		}else if("F".equals(fp) || "D".equals(fp) ){				
			PagoDeDiferencias pdd=new PagoDeDiferencias();
			if("F".equals(fp)){
				pdd.setCambiaria(Boolean.TRUE);
			}
			p=pdd;
		}else if("X".equals(fp)){
			p=new PagoConEfectivo();
			p.setComentario("Importado, orignalmente forma de pago X");
		}else{
			update(null);
			throw new RuntimeException("Forma de pago no valida en el esquema actual: "+fp);
		}
		Long id=rs.getLong("PAGO_ID");
		String origen=rs.getString("ORIGEN");
		Long sucursal_id=rs.getLong("SUCURSAL");
		
		p.setSiipapId(id);
		//p.setFolio(numero.intValue());
		p.setSucursal(ImportadorSupport.getInstance().buscarSucursal(sucursal_id.intValue()));
		p.setOrigen(OrigenDeOperacion.valueOf(origen));
		
		String cliente=rs.getString("CLAVE");
		Cliente c=ServiceLocator2.getClienteManager().buscarPorClave(cliente);
		if(c==null){
			logger.info("Cliente no existe: "+cliente);
			update(null);
			return;
		}			
		p.setCliente(c);
		
		Date fecha=rs.getDate("FECHA");
		p.setFecha(fecha);
		
		p.setTotal(total);
		if(StringUtils.isBlank(p.getComentario()))
			p.setComentario(COMENTARIO);
		
		System.out.println("Procesando id:"+rs.getLong("PAGO_ID")+ p);
		
		// Procesamos la aplicacion
		
		Long cargo_id=rs.getLong("VENTA_ID");
		if(cargo_id==null){
			cargo_id=rs.getLong("NOTA_ID");
			
		}
		
		AplicacionDePago ap=new AplicacionDePago();
		ap.setAbono(p);
		p.getAplicaciones().add(ap);
		
		Cargo cargo=buscarCargo(cargo_id);
		if(cargo==null){
			logger.info("No localizo el cargo para el pago  CARGO_ID="+cargo_id);
			update(null);
			return;
			
		}
		
		ap.setCargo(cargo);
		ap.setFecha(fecha);
		ap.setComentario("Aplicacion automatica ");
		ap.setImporte(total);
		ap.setSiipapId(id);
		ap.actualizarDetalle();
		
		
		persistirPago(p);
	}
	
	private void persistirPago(Pago p){
		try {
			Pago existe=buscarPagoPorSiipapId(p.getSiipapId());
			if(existe!=null){				
				logger.debug("Pago existente eliminandolo ");
				ServiceLocator2.getUniversalDao().remove(Pago.class, existe.getId());
			}
			p=(Pago)ServiceLocator2.getUniversalManager().save(p);
			update(p);
		} catch (ImportacionCanceledException e) {
			throw e;
		}catch (Exception e) {
			logger.info("No se pudo persistir el pago: "+p);
			logger.error(ExceptionUtils.getRootCauseMessage(e),e);
		}
	}
	
	
	
	public int contarRegistros(final Periodo periodo){
		
		String sql="SELECT count(*) FROM SW_PAGOS  A WHERE A.FECHA BETWEEN ? AND ? " +
		" AND ORIGEN IN(\'MOS\',\'CAM\')" +
		" AND FORMADEPAGO NOT IN(\'U\',\'T\',\'A\',\'S\',\'K\')" +
		" AND IMPORTE>0 ORDER BY PAGO_ID ";
		
		Object[] params=new Object[]{
				new SqlParameterValue(Types.DATE,periodo.getFechaInicial())	
				,new SqlParameterValue(Types.DATE,periodo.getFechaFinal())
			};
			int tot=getOrigenTemplate().queryForInt(sql,params);
			return tot;
	}
	
	public Pago buscarPagoPorSiipapId(Long siipapId){
		List<Pago> data=getHibernate().find("from Pago p  left join fetch p.aplicaciones ap where p.siipapId=?", siipapId);		
		return data.isEmpty()?null:data.get(0);
	}
	
	private Cargo buscarCargo(Long id){
		List<Cargo> data=getHibernate().find("from Cargo c  where c.siipapWinId=?", id);		
		return data.isEmpty()?null:data.get(0);
	}	
	
	protected void update(Pago p)throws ImportacionCanceledException{
	}
	
	
	public JdbcTemplate getOrigenTemplate(){
		return ServiceLocator2.getAnalisisJdbcTemplate();
	}
	
	public HibernateTemplate getHibernate(){
		return ServiceLocator2.getHibernateTemplate();
	}
	
	
	
	
	private static ImportadorDePagosDeContado INSTANCE;
	
	public static ImportadorDePagosDeContado getInstance(){
		if(INSTANCE==null)
			INSTANCE=new ImportadorDePagosDeContado();
		return INSTANCE;
			
	}

	public static void main(String[] args) {
		DBUtils.whereWeAre();		
		ImportadorDePagosDeContado imp=new ImportadorDePagosDeContado();
		imp.importar(new Periodo("01/01/2009","31/01/2009"));		
	}

	
}
